﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Xml;
using System.ComponentModel;
using Sharkbite.Irc;
using System.IO;
using System.Xml.Serialization;

namespace CSharpIrcBot
{
    //public class ConnectionSettings : ConfigurationSection
    //{
    //    [ConfigurationProperty( "Connections", IsDefaultCollection = true )]
    //    public ConnectionCollection Connections
    //    {
    //        get { return (ConnectionCollection) base["Connections"]; }
    //    }
    //}

    //public sealed class ConnectionElement : ConfigurationElement
    //{
    //    [ConfigurationProperty( "HostName", IsKey = true, IsRequired = true )]
    //    public string HostName
    //    {
    //        get { return (string) this["HostName"]; }
    //        set { this["HostName"] = value; }
    //    }
    //    [ConfigurationProperty( "Port", IsRequired = true )]
    //    public int Port
    //    {
    //        get { return Convert.ToInt32( this["Port"] ); }
    //        set { this["Port"] = value; }
    //    }
    //    [ConfigurationProperty( "RealName", IsRequired = true )]
    //    public string RealName
    //    {
    //        get { return (string) this["RealName"]; }
    //        set { this["RealName"] = value; }
    //    }
    //    [ConfigurationProperty( "NickName", IsRequired = true )]
    //    public string NickName
    //    {
    //        get { return (string) this["NickName"]; }
    //        set { this["NickName"] = value; }
    //    }
    //    [ConfigurationProperty( "UserName", IsRequired = true )]
    //    public string UserName
    //    {
    //        get { return (string) this["UserName"]; }
    //        set { this["UserName"] = value; }
    //    }
    //    [ConfigurationProperty( "ModeMask", IsRequired = true )]
    //    public string ModeMask
    //    {
    //        get { return (string) this["ModeMask"]; }
    //        set { this["ModeMask"] = value; }
    //    }
    //}

    //public sealed class ConnectionCollection : ConfigurationElementCollection
    //{
    //    protected override ConfigurationElement CreateNewElement()
    //    {
    //        return new ConnectionElement();
    //    }

    //    protected override object GetElementKey( ConfigurationElement element )
    //    {
    //        return ( (ConnectionElement) element ).HostName;
    //    }

    //    public override ConfigurationElementCollectionType CollectionType
    //    {
    //        get
    //        {
    //            return ConfigurationElementCollectionType.BasicMap;
    //        }
    //    }

    //    protected override string ElementName
    //    {
    //        get
    //        {
    //            return "Connection";
    //        }
    //    }

    //    public ConnectionElement this[int index]
    //    {
    //        get { return (ConnectionElement) BaseGet( index ); }
    //        set
    //        {
    //            if( BaseGet( index ) != null )
    //            {
    //                BaseRemoveAt( index );
    //            }
    //            BaseAdd( index, value );
    //        }
    //    }

    //    new public ConnectionElement this[string HostName]
    //    {
    //        get { return (ConnectionElement) BaseGet( HostName ); }
    //    }

    //    public bool ContainsKey( string key )
    //    {
    //        bool result = false;
    //        object[] keys = BaseGetAllKeys();
    //        foreach( object obj in keys )
    //        {
    //            if( (string) obj == key )
    //            {
    //                result = true;
    //                break;
    //            }
    //        }
    //        return result;
    //    }
    //}

    [Serializable]
    public class ConnectionSettings : List<Connection>
    {
        public Connection this[string hostName]
        {
            get
            {
                foreach( Connection c in this )
                {
                    if( c.HostName == hostName )
                    {
                        return c;
                    }
                }
                return null;
            }
        }
        public static ConnectionSettings LoadConnections()
        {
            if( !File.Exists( Global.UserDataPath + "connections.xml"))
            {
                return new ConnectionSettings();
            }
            using( var stream = File.OpenRead( Global.UserDataPath + "connections.xml" ) )
            {
                XmlSerializer serializer = new XmlSerializer( typeof( ConnectionSettings ) );
                return (ConnectionSettings)serializer.Deserialize( stream );
            }
        }
        public static void SaveConnections( object obj )
        {
            if( ( obj is ConnectionSettings ) )
            {
                ConnectionSettings connections = obj as ConnectionSettings;
                XmlSerializer serializer = new XmlSerializer( typeof( ConnectionSettings ) );
                if (!Directory.Exists(Global.UserDataPath))
                {
                    Directory.CreateDirectory( Global.UserDataPath );
                }
                using( var stream = File.Create( Global.UserDataPath + "connections.xml" ) )
                {
                    serializer.Serialize( stream, connections );
                }
            }
        }

    }

    [Serializable]
    public class Connection : NotifyBase
    {
        private string hostName;
        [DisplayName( "Host Name" )]
        public string HostName
        {
            get { return hostName; }
            set { SetField( ref hostName, value, "HostName" ); }
        }

        private int port;
        [DisplayName( "Host Port" )]
        public int Port
        {
            get { return port; }
            set { SetField( ref port, value, "Host Prot" ); }
        }

        private string realName;
        [DisplayName( "Real Name" )]
        public string RealName
        {
            get { return realName; }
            set { SetField( ref realName, value, "Real Name" ); }
        }

        private string nickName;
        [DisplayName( "Nick Name" )]
        public string NickName
        {
            get { return nickName; }
            set { SetField( ref nickName, value, "Nick Name" ); }
        }

        private string userName;
        [DisplayName( "User Name" )]
        public string UserName
        {
            get { return userName; }
            set { SetField( ref userName, value, "User Name" ); }
        }

        private string modeMask;
        [DisplayName( "Mode Mask" )]
        public string ModeMask
        {
            get { return modeMask; }
            set { SetField( ref modeMask, value, "Mode Mask" ); }
        }

        public List<string> Channels { get; set; }

        public Connection()
        {
            Channels = new List<string>();
        }

        public ConnectionArgs GetConnectionArgs()
        {
            ConnectionArgs cArgs = new ConnectionArgs();
            cArgs.Hostname = HostName;
            cArgs.Port = Port;
            cArgs.RealName = RealName;
            cArgs.Nick = NickName;
            cArgs.UserName = UserName;
            cArgs.ModeMask = ModeMask;
            return cArgs;
        }
    }

    [Serializable]
    public class NotifyBase
    {
        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        protected bool SetField<T>( ref T field, T value, string propertyName )
        {
            if( !EqualityComparer<T>.Default.Equals( field, value ) )
            {
                field = value;
                OnPropertyChanged( propertyName );
                return true;
            }
            return false;
        }

        protected virtual void OnPropertyChanged( string propertyName )
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if( handler != null )
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

}
